package com.junjie.base.tool;

import com.alibaba.fastjson.JSONObject;
import com.junjie.base.annotation.NettyController;
import com.junjie.base.annotation.NettyRequestMapping;
import com.junjie.base.annotation.RequestMethod;
import io.netty.buffer.ByteBuf;
import io.netty.handler.codec.http.FullHttpRequest;
import io.netty.handler.codec.http.HttpMethod;
import io.netty.util.CharsetUtil;

import java.io.IOException;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.lang.reflect.Parameter;
import java.util.ArrayList;
import java.util.List;

/**
 * @Author Jun jie Yi
 * @Date 2022/3/7 22:01
 */
public class ControllerUtil {

    //注解容器，存储加了注解的类
    private static List<Class> clazzs = null;

    public static JSONObject useController(FullHttpRequest req) {

        //返回值
        JSONObject res = null;

        if (clazzs == null) {
            try {
                clazzs = getControllerClass();
            } catch (IOException e) {
                e.printStackTrace();
            } catch (ClassNotFoundException e) {
                e.printStackTrace();
            }
        }

        for (Class clazz : clazzs) {
            NettyController anno_controller = (NettyController) clazz.getAnnotation(NettyController.class);
            Method[] methods = clazz.getDeclaredMethods();
            for (Method method : methods) {
                //加了注解的方法
                if (method.isAnnotationPresent(NettyRequestMapping.class)) {
                    //通过getAnnotation可以获取注解对象
                    NettyRequestMapping annotation = method.getAnnotation(NettyRequestMapping.class);
                    //地址
                    String url = anno_controller.url() + annotation.url();
                    //类型
                    RequestMethod type = annotation.method();
                    //是否有地址匹配上
                    if (req.uri().equals(url)) {
                        if ((type.equals(RequestMethod.GET) && req.method() == HttpMethod.GET) || (type.equals(RequestMethod.POST) && req.method() == HttpMethod.POST)) {
                            try {
                                res = new JSONObject();
                                Object data = null;
                                //调用方法，先判断是否含有1参数
                                int parameterCount = method.getParameterCount();
                                if (parameterCount == 1) {
                                    data = method.invoke(clazz.newInstance(), parseJSONRequest(req));
                                } else if (parameterCount == 0) {
                                    data = method.invoke(clazz.newInstance());
                                }
                                //如果返回的数据是空
                                if (data == null) {
                                    res.put("code", 500);
                                    res.put("warning", "return data is null");
                                } else {
                                    res.put("code", 200);
                                    res.put("data", data);
                                }
                            } catch (IllegalAccessException e) {
                                e.printStackTrace();
                            } catch (InvocationTargetException e) {
                                e.printStackTrace();
                            } catch (InstantiationException e) {
                                e.printStackTrace();
                            }
                        } else {
                            res = new JSONObject();
                            res.put("code", 400);
                            res.put("error", type + " type is false, please check the request method");
                        }
                    }
                }
            }
        }

        if ("/favicon.ico".equals(req.uri())) {
            res = new JSONObject();
        }
        if (res == null) {
            res = new JSONObject();
            res.put("code", 400);
            res.put("error", "No uri match!");
        }
        return res;
    }

    //获取所有加了NettyController注解的类，将加了注解的类加入容器
    public static List<Class> getControllerClass() throws IOException, ClassNotFoundException {
        List<Class> lc = new ArrayList<>();
        List<String> filesName = GetFileName.getFilesName();
        for (String name : filesName) {
            Class clazz = Class.forName(name);
            //如果类里面包含这个注解
            if (clazz.isAnnotationPresent(NettyController.class)) {
                lc.add(clazz);
            }
        }
        return lc;
    }

    /**
     * 获取请求的内容
     *
     * @param request
     * @return
     */
    private static JSONObject parseJSONRequest(FullHttpRequest request) {
        ByteBuf jsonBuf = request.content();
        String jsonStr = jsonBuf.toString(CharsetUtil.UTF_8);
        JSONObject jsonObject = JSONObject.parseObject(jsonStr); //将json字符串转成JSONObject对象
        return jsonObject;
    }
}
